#ifndef __PE_TRUNK__
#define __PE_TRUNK__

#include "thisinc.h"

#pragma pack(1)

namespace wpe
{
	enum 
	{
		WPE_IMAGE_DOS_SIGNATURE				= 0x5A4D,      // MZ
		WPE_IMAGE_NT_SIGNATURE				= 0x00004550,  // PE00
		WPE_IMAGE_FILE_MACHINE_I386			= 0x014c,  // Intel 386.
		WPE_IMAGE_FILE_MACHINE_AMD64		= 0x8664,  // AMD64 (K8)
		WPE_IMAGE_FILE_32BIT_MACHINE		= 0x0100,
		WPE_IMAGE_NT_OPTIONAL_HDR32_MAGIC	= 0x10b,
		WPE_IMAGE_NT_OPTIONAL_HDR64_MAGIC	= 0x20b,
		WPE_IMAGE_SIZEOF_SHORT_NAME			= 8,
		WPE_IMAGE_DIRECTORY_ENTRY_IMPORT	= 1,  // Import Directory
		WPE_IMAGE_DIRECTORY_ENTRY_RESOURCE	= 2,
		WPE_IMAGE_DIRECTORY_ENTRY_EXPORT	= 0,

		WPE_IMAGE_SCN_LNK_NRELOC_OVFL		= 0x01000000,  // Section contains extended relocations.
		WPE_IMAGE_SCN_MEM_DISCARDABLE		= 0x02000000,  // Section can be discarded.
		WPE_IMAGE_SCN_MEM_NOT_CACHED		= 0x04000000,  // Section is not cachable.
		WPE_IMAGE_SCN_MEM_NOT_PAGED			= 0x08000000,  // Section is not pageable.
		WPE_IMAGE_SCN_MEM_SHARED			= 0x10000000,  // Section is shareable.
		WPE_IMAGE_SCN_MEM_EXECUTE			= 0x20000000,  // Section is executable.
		WPE_IMAGE_SCN_MEM_READ				= 0x40000000,  // Section is readable.
		WPE_IMAGE_SCN_MEM_WRITE				= 0x80000000,  // Section is writeable.
		WPE_IMAGE_SCN_CNT_CODE				= 0x00000020,  // Section contains code.

		WPE_IMAGE_FILE_DLL					= 0x2000,  // File is a DLL.
	};

	typedef struct _WPE_IMAGE_DOS_HEADER {      // DOS .EXE header
		le::U16	e_magic;                     // Magic number
		le::U16	e_cblp;                      // Bytes on last page of file
		le::U16	e_cp;                        // Pages in file
		le::U16	e_crlc;                      // Relocations
		le::U16	e_cparhdr;                   // Size of header in paragraphs
		le::U16	e_minalloc;                  // Minimum extra paragraphs needed
		le::U16	e_maxalloc;                  // Maximum extra paragraphs needed
		le::U16	e_ss;                        // Initial (relative) SS value
		le::U16	e_sp;                        // Initial SP value
		le::U16	e_csum;                      // Checksum
		le::U16	e_ip;                        // Initial IP value
		le::U16	e_cs;                        // Initial (relative) CS value
		le::U16	e_lfarlc;                    // File address of relocation table
		le::U16	e_ovno;                      // Overlay number
		le::U16	e_res[4];                    // Reserved words
		le::U16	e_oemid;                     // OEM identifier (for e_oeminfo)
		le::U16	e_oeminfo;                   // OEM information; e_oemid specific
		le::U16	e_res2[10];                  // Reserved words
		le::I32	e_lfanew;                    // File address of new exe header
	} __attribute__((packed)) WPE_IMAGE_DOS_HEADER, *PWPE_IMAGE_DOS_HEADER;

	typedef struct _WPE_IMAGE_FILE_HEADER {
		le::U16	Machine;
		le::U16	NumberOfSections;
		le::U32	TimeDateStamp;
		le::U32	PointerToSymbolTable;
		le::U32	NumberOfSymbols;
		le::U16	SizeOfOptionalHeader;
		le::U16	Characteristics;
	} __attribute__((packed)) WPE_IMAGE_FILE_HEADER, *PWPE_IMAGE_FILE_HEADER;


	//
	// Directory format.
	//

	typedef struct _WPE_IMAGE_DATA_DIRECTORY {
		le::U32	VirtualAddress;
		le::U32	Size;
	} __attribute__((packed)) WPE_IMAGE_DATA_DIRECTORY, *PWPE_IMAGE_DATA_DIRECTORY;

	enum { WPE_IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16 };

	//
	// Optional header format.
	//

	typedef struct _WPE_IMAGE_OPTIONAL_HEADER {
		//
		// Standard fields.
		//

		le::U16	Magic;
		uint8_t	MajorLinkerVersion;
		uint8_t	MinorLinkerVersion;
		le::U32	SizeOfCode;
		le::U32	SizeOfInitializedData;
		le::U32	SizeOfUninitializedData;
		le::U32	AddressOfEntryPoint;
		le::U32	BaseOfCode;
		le::U32	BaseOfData;

		//
		// NT additional fields.
		//

		le::U32	ImageBase;
		le::U32	SectionAlignment;
		le::U32	FileAlignment;
		le::U16	MajorOperatingSystemVersion;
		le::U16	MinorOperatingSystemVersion;
		le::U16	MajorImageVersion;
		le::U16	MinorImageVersion;
		le::U16	MajorSubsystemVersion;
		le::U16	MinorSubsystemVersion;
		le::U32	Win32VersionValue;
		le::U32	SizeOfImage;
		le::U32	SizeOfHeaders;
		le::U32	CheckSum;
		le::U16	Subsystem;
		le::U16	DllCharacteristics;
		le::U32	SizeOfStackReserve;
		le::U32	SizeOfStackCommit;
		le::U32	SizeOfHeapReserve;
		le::U32	SizeOfHeapCommit;
		le::U32	LoaderFlags;
		le::U32	NumberOfRvaAndSizes;
		WPE_IMAGE_DATA_DIRECTORY	DataDirectory[WPE_IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
	} __attribute__((packed)) WPE_IMAGE_OPTIONAL_HEADER32, *PWPE_IMAGE_OPTIONAL_HEADER32;

	typedef struct _IMAGE_OPTIONAL_HEADER64 {
		le::U16	Magic;
		uint8_t	MajorLinkerVersion;
		uint8_t	MinorLinkerVersion;
		le::U32	SizeOfCode;
		le::U32	SizeOfInitializedData;
		le::U32	SizeOfUninitializedData;
		le::U32	AddressOfEntryPoint;
		le::U32	BaseOfCode;
		le::U64	ImageBase;
		le::U32	SectionAlignment;
		le::U32	FileAlignment;
		le::U16	MajorOperatingSystemVersion;
		le::U16	MinorOperatingSystemVersion;
		le::U16	MajorImageVersion;
		le::U16	MinorImageVersion;
		le::U16	MajorSubsystemVersion;
		le::U16	MinorSubsystemVersion;
		le::U32	Win32VersionValue;
		le::U32	SizeOfImage;
		le::U32	SizeOfHeaders;
		le::U32	CheckSum;
		le::U16	Subsystem;
		le::U16	DllCharacteristics;
		le::U64	SizeOfStackReserve;
		le::U64	SizeOfStackCommit;
		le::U64	SizeOfHeapReserve;
		le::U64	SizeOfHeapCommit;
		le::U32	LoaderFlags;
		le::U32	NumberOfRvaAndSizes;
		WPE_IMAGE_DATA_DIRECTORY DataDirectory[WPE_IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
	} WPE_IMAGE_OPTIONAL_HEADER64, *PWPE_IMAGE_OPTIONAL_HEADER64;

	typedef struct _WPE_IMAGE_NT_HEADERS {
		le::U32 Signature;
		WPE_IMAGE_FILE_HEADER FileHeader;
		WPE_IMAGE_OPTIONAL_HEADER32 OptionalHeader;
	} __attribute__((packed)) WPE_IMAGE_NT_HEADERS32, *PWPE_IMAGE_NT_HEADERS32;
	

	//
	// Import Format
	//

	typedef struct _WPE_IMAGE_IMPORT_BY_NAME {
		le::U16	Hint;
		char	Name[1];
	} __attribute__((packed)) WPE_IMAGE_IMPORT_BY_NAME, *PWPE_IMAGE_IMPORT_BY_NAME;

	typedef struct _WPE_IMAGE_THUNK_DATA32 {
		typedef uint32_t	thunk_value_t;
		le::U32	MixData;
	} __attribute__((packed)) WPE_IMAGE_THUNK_DATA32, * PWPE_IMAGE_THUNK_DATA32;

	typedef struct _WPE_IMAGE_THUNK_DATA64 {
		typedef uint64_t	thunk_value_t;
		le::U64	MixData;
	} __attribute__((packed)) WPE_IMAGE_THUNK_DATA64, * PWPE_IMAGE_THUNK_DATA64;

	typedef struct _WPE_IMAGE_IMPORT_DESCRIPTOR {
		le::U32	OriginalFirstThunk;
		le::U32	TimeDateStamp;                  // 0 if not bound,
		le::U32	ForwarderChain;                 // -1 if no forwarders
		le::U32	Name;
		le::U32	FirstThunk;                     // RVA to IAT (if bound this IAT has actual addresses)
	} __attribute__((packed)) WPE_IMAGE_IMPORT_DESCRIPTOR, *PWPE_IMAGE_IMPORT_DESCRIPTOR;


	//
	// Section header format.
	//



	typedef struct _WPE_IMAGE_SECTION_HEADER {
		uint8_t	Name[WPE_IMAGE_SIZEOF_SHORT_NAME];
		le::U32	VirtualSize;
		le::U32	VirtualAddress;
		le::U32	SizeOfRawData;
		le::U32	PointerToRawData;
		le::U32	PointerToRelocations;
		le::U32	PointerToLinenumbers;
		le::U16	NumberOfRelocations;
		le::U16	NumberOfLinenumbers;
		le::U32	Characteristics;
	} __attribute__((packed)) WPE_IMAGE_SECTION_HEADER, *PWPE_IMAGE_SECTION_HEADER;

	typedef struct _WPE_IMAGE_EXPORT_DIRECTORY {
		le::U32	Characteristics;
		le::U32	TimeDateStamp;
		le::U16	MajorVersion;
		le::U16	MinorVersion;
		le::U32	Name;
		le::U32	Base;
		le::U32	NumberOfFunctions;
		le::U32	NumberOfNames;
		le::U32	AddressOfFunctions;     // RVA from base of image
		le::U32	AddressOfNames;         // RVA from base of image
		le::U32	AddressOfNameOrdinals;  // RVA from base of image
	} __attribute__((packed)) WPE_IMAGE_EXPORT_DIRECTORY, *PWPE_IMAGE_EXPORT_DIRECTORY;



};

#pragma pack()

#endif